package com.piece.core.framework.util.net;

import com.piece.core.framework.exception.ServerException;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.file.FileUtil;
import com.piece.core.framework.util.basic.SpringUtil;
import com.piece.core.framework.util.string.JsonUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.framework.properties.ApplicationProperties;
import lombok.Data;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@Setter
public class WeatherUtil {

    private static final String[] weatherV = new String[]{"晴", "多云", "云", "雨", "雨夹雪", "雪", "风", "雾", "霾"};

    private static final String[] weatherK = new String[]{"clear-day", "partly-cloudy-day", "cloudy", "rain", "sleet", "snow", "wind", "fog", "fog"};

    private static final ReentrantLock lock = new ReentrantLock();

    private String url;
    private Map<String, String> cityMap;

    private static WeatherUtil instance;

    public static WeatherUtil getInstance() {
        if (null == instance) {
            lock.lock();
            if (null == instance) {
                instance = new WeatherUtil();
                ApplicationProperties properties = SpringUtil.getBean(ApplicationProperties.class);
                instance.setUrl(properties.getWeatherUrl());

                // 加载城市编码数据
                String cityFileName = properties.getWeatherCityFile();
                try {
                    InputStream inputStream = WeatherUtil.class.getClassLoader().getResourceAsStream(cityFileName);
                    // 获取项目路径
                    Properties props = System.getProperties();
                    String rootPath = props.getProperty("user.dir");
                    File upload = new File(rootPath, "upload/weather");
                    if (!upload.exists()) {
                        upload.mkdirs();
                    }
                    upload = new File(rootPath, "upload/weather/" + cityFileName);
                    if (upload.exists()) {
                        upload.delete();
                    }
                    upload.createNewFile();

                    FileUtil.write(upload, inputStream);
                    String text = FileUtil.readTextFile(upload);
                    List<City> cityList = JsonUtil.toList(text, City.class);
                    HashMap cityMap = new HashMap<>();
                    cityList.forEach(city -> {
                        cityMap.put(city.city_name, city.getCity_code());
                    });
                    instance.setCityMap(cityMap);
                } catch (Exception e) {
                    log.error("天气预报城市文件读取异常：{}", e.getMessage());
                }
            }
            lock.unlock();
        }
        return instance;
    }

    /**
     * 获取城市编码
     */
    public String getCityCode(String cityName) {
        return this.cityMap.get(cityName);
    }

    /**
     * 获取天气结果数据
     */
    public Map getCityWeather(String cityCode) {
        String url = this.url + cityCode;
        AjaxResponse result = HttpUtil.get(url).execute().html();
        Map response = null;
        if (result.isSuccess()) {
            response = JsonUtil.toMap(Convert.toStr(result.getParam()));
        } else {
            throw new ServerException();
        }
        response = (Map) response.get("data");

        Map forecast = ((List<Map>) response.get("forecast")).get(0);
        int index = StringUtil.findIndexOfList(weatherV, (String) forecast.get("type"), true);
        response.put("canvas", weatherK[index]);
        response.put("type", forecast.get("type"));
        String high = (String) forecast.get("high");
        if (StringUtil.isNotEmpty(high)) {
            high = high.replace("℃", "");
            response.put("high", high);
        }
        String low = (String) forecast.get("low");
        if (StringUtil.isNotEmpty(low)) {
            low = low.replace("℃", "");
            response.put("low", low);
        }
        response.put("fx", forecast.get("fx"));
        response.put("fl", forecast.get("fl"));
        return response;
    }

    /**
     * 天气结果转成Charts报表
     */
    public Map transToCharts(Map weather) {
        Map response = new HashMap();
        // 生成xAxis category
        List<String> category = new ArrayList<>();
        // 生成series data
        List<Double> series_data_high = new ArrayList<>();
        List<Double> series_data_low = new ArrayList<>();
        List<Map> forecast = (List<Map>) weather.get("forecast");

        forecast = forecast.subList(0, 7);

        forecast.forEach(data -> {
            category.add((String) data.get("week"));
            series_data_high.add(StringUtil.patternNumber((String) data.get("high")));
            series_data_low.add(StringUtil.patternNumber((String) data.get("low")));
        });

        response.put("category", category);
        response.put("high", series_data_high);
        response.put("low", series_data_low);
        return response;
    }

    @Data
    public static class City {
        String id;
        String pid;
        String city_code;
        String city_name;
        String post_code;
        String area_code;
        String ctime;
    }
}
